package com.rs.config;

import com.rs.service.GwService;
import com.rs.service.impl.GwServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;

@Configuration
public class CxfServerConfig {

    @Value("${client-name-space}")
    private String nameSpace;
    @Value("${server-port}")
    private String port;

    @Bean
    public ServletRegistrationBean createDispatcherServlet() {
        return new ServletRegistrationBean(new CXFServlet(),"/public/soc/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus cxfBus() {
        return new SpringBus();
    }

    @Bean
    public GwService gmService() {
        if (StringUtils.isEmpty(nameSpace)) {
            InetAddress addr = null;
            try {
                addr = InetAddress.getLocalHost();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            assert addr != null;
            String ip = addr.getHostAddress();
            nameSpace = "http://" + ip + ":" + port + "/public/soc/gwService?wsdl";
        }
        modifyTargetNameSpace(GwService.class, nameSpace);
        modifyTargetNameSpace(GwServiceImpl.class, nameSpace);
        return new GwServiceImpl();
    }

    @Bean(name = "cxfEndpoint")
    public Endpoint cxfEndpoint() {
        EndpointImpl endpoint = new EndpointImpl(cxfBus(), gmService());
        endpoint.getInInterceptors().add(new LoggingInInterceptor());
        endpoint.getOutInterceptors().add(new LoggingOutInterceptor());
        endpoint.publish("/gwService");
        return endpoint;
    }

    private void modifyTargetNameSpace(Class<?> t, String amespace) {
        try {
            WebService webService = t.getAnnotation(WebService.class);
            InvocationHandler handler = Proxy.getInvocationHandler(webService);
            Field field = handler.getClass().getDeclaredField("memberValues");
            field.setAccessible(true);
            Map map = (Map) field.get(handler);
            map.put("targetNamespace", amespace);
        } catch (Exception ignored) {
        }
    }
}
